package flib;

import java.util.Collections;
import java.util.HashMap;
import java.util.Vector;

import processing.core.PApplet;
import simpleGeom.Vec2D;
import simpleGeom.Vec3D;

public class MarkovLearn extends PApplet {
	Vector<Vec2D> points = new Vector<Vec2D>();
	Vector<Vec2D> points2 = new Vector<Vec2D>();
	Vector<Vector<Float>> angles = new Vector<Vector<Float>>();
	int nAngles = 32;

	float maxL = 20;
	float maxA = PI * 2f;
	float dAngle = maxA / nAngles;
	HashMap<Float, Vector<Float>> deltaAngles;

	public void setup() {
		size(800, 800);
		rectMode(CENTER);
	}

	public void draw() {
		background(0);
		if (flagInit) {
			initFile();
			flagInit = false;
		}
		if (mousePressed && frameCount % 2 == 0) {
			Vec2D newP = new Vec2D(mouseX, mouseY);
			if (points.size() == 0) {
				points.add(newP);
			} else {
				Vec2D oldP = points.lastElement();
				Vec2D v = Vec2D.sub(newP, oldP);
				float l = v.mag();
				if (l > maxL) {
					int nP = (int) (l / maxL) + 1;
					v.normalize();
					float cD = l / nP;
					for (int i = 1; i <= nP; i++) {
						Vec2D cV = Vec2D.mult(v, i * cD);
						cV.add(oldP);
						points.add(cV);
					}
				}
			}
			// points.add(new Vec2D(mouseX,mouseY));

		}
		stroke(255);
		display(points);
		stroke(255, 0, 0);
		display(points2);
	}

	public void initFile() {
		println("points.sze" + points.size());
		angles = new Vector<Vector<Float>>();

		for (int i = 0; i < nAngles; i++) {
			Vector<Float> angleR = new Vector<Float>();
			// Float f=new Float(i*maxA/nAngles);

			// angleR.add(new Float(0));
			// angleR.add(new Float(random(maxA)));
			// angleR.add(f);
			angles.add(angleR);
		}
		float lastDeltaAngle = 0;
		for (int i = 0; i < points.size() - 2; i++) {
			Vec2D v1 = points.get(i);
			Vec2D v2 = points.get(i + 1);
			Vec2D v3 = points.get(i + 2);
			Vec2D v12 = Vec2D.sub(v2, v1);
			Vec2D v23 = Vec2D.sub(v3, v2);
			float a1 = Vec2D.getTheta(v12);

			// if (a1<0)a1=maxA+a1;
			float a2 = Vec2D.getTheta(v23);
			// if (a2<0)a2=maxA+a2;

			float dAngle = a2 - a1;
			dAngle = (float) Vec2D.getAngleBetweenCCW(a1, a2);
			println("dAngle: " + dAngle);
			if (dAngle < 0)
				dAngle = maxA + dAngle;
			// dAngles.add(dAngle);
			// println("Angle: "+a1);

			Vector<Float> angleR = getAngleTable(lastDeltaAngle);
			dAngle = getRoundedAngle(dAngle);

			angleR.add(dAngle);
			lastDeltaAngle = dAngle;
			// angleR.add(a2+dAngle);
			// angleR.add(a2-dAngle);

		}
		copy(100);
	}

	public void display(Vector<Vec2D> points) {
		for (int i = 0; i < points.size() - 1; i++) {
			Vec2D v1 = points.get(i);
			rect(v1.x, v1.y, 2, 2);
			Vec2D v2 = points.get(i + 1);
			line(v1.x, v1.y, v2.x, v2.y);
		}
	}

	public float getNextAngle(float l) {
		Vector<Float> angleR = getAngleTable(l);
		if (angleR.size() == 0)
			return 0;
		Collections.shuffle(angleR);
		return angleR.get(0);
	}

	public void copy(int n) {
		points2 = new Vector<Vec2D>();
		points2.add(new Vec2D(width * 0.5f, height * 0.5f));
		points2.add(new Vec2D(width * 0.5f + maxL, height * 0.5f));
		float lastAngle = 0;
		float lastDelta = 0;
		float lastX = width * 0.5f;
		float lastY = height * 0.5f;
		float lastL = maxL;
		for (int i = 0; i < n; i++) {

			lastAngle += lastDelta;
			lastDelta = getNextAngle(lastDelta);

			Vec2D newPos = Vec2D.getPolar(lastAngle, lastL);
			lastX += newPos.x;
			lastY += newPos.y;
			points2.add(new Vec2D(lastX, lastY));
		}
	}

	float getRoundedAngle(float angle) {
		if (angle >= maxA)
			angle = angle % maxA;
		int iAngle = Math.round(angle / dAngle);
		// if (iAngle==nAngles)iAngle=0;
		return iAngle * dAngle;
	}

	Vector<Float> getAngleTable(float angle) {
		if (angle >= maxA)
			angle = angle % maxA;

		int cI = Math.round((angle * nAngles / maxA));
		// if (cI>=angles.size())return angles.get(0);
		return angles.get(cI);

		// return angles.get(cI);
	}

	boolean flagInit;

	public void keyPressed() {
		if (key == 's') {
			flagInit = true;
		}
	}

	public void mousePressed() {
		points = new Vector<Vec2D>();

	}

}
